home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / win / tclWin16.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  11.4 KB  |  348 lines  |  [TEXT/CWIE]

  1. /*
  2.  * tclWin16.c --
  3.  *
  4.  *      This file contains code for a 16-bit DLL to handle 32-to-16 bit
  5.  *      thunking. This is necessary for the Win32s SynchSpawn() call.
  6.  *
  7.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tclWin16.c 1.18 97/05/23 13:13:32
  13.  */
  14.  
  15. #define STRICT
  16.  
  17. #include <windows.h>  
  18. #include <toolhelp.h> 
  19.  
  20. #include <stdio.h>
  21. #include <string.h>
  22.  
  23. static int                      WinSpawn(char *command);
  24. static int                      DosSpawn(char *command, char *fromFileName,
  25.                     char *toFileName);                                          
  26. static int                      WaitForExit(int inst);
  27.  
  28. /*
  29.  * The following data is used to construct a .pif file that wraps the
  30.  * .bat file that runs the 16-bit application (that Jack built).  
  31.  * The .pif file causes the .bat file to run in an iconified window.
  32.  * Otherwise, when we try to exec something, a DOS box pops up, 
  33.  * obscuring everything, and then almost immediately flickers out of
  34.  * existence, which is rather disconcerting.
  35.  */
  36.  
  37. static char pifData[545] = {
  38. '\000', '\013', '\040', '\040', '\040', '\040', '\040', '\040', 
  39. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  40. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  41. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  42. '\200', '\000', '\200', '\000', '\103', '\117', '\115', '\115', 
  43. '\101', '\116', '\104', '\056', '\103', '\117', '\115', '\000', 
  44. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  45. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  46. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  47. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  48. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  49. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
  50. '\040', '\040', '\040', '\020', '\000', '\000', '\040', '\040', 
  51. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  52. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  53. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  54. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  55. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  56. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  57. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
  58. '\040', '\040', '\040', '\040', '\040', '\000', '\000', '\000', 
  59. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  60. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  61. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  62. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  63. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  64. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  65. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  66. '\000', '\000', '\000', '\000', '\000', '\177', '\001', '\000', 
  67. '\377', '\031', '\120', '\000', '\000', '\007', '\000', '\000', 
  68. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  69. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  70. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  71. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  72. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  73. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  74. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  75. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
  76. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  77. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  78. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  79. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  80. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  81. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  82. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  83. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\340', 
  84. '\040', '\115', '\111', '\103', '\122', '\117', '\123', '\117', 
  85. '\106', '\124', '\040', '\120', '\111', '\106', '\105', '\130', 
  86. '\000', '\207', '\001', '\000', '\000', '\161', '\001', '\127', 
  87. '\111', '\116', '\104', '\117', '\127', '\123', '\040', '\063',
  88. '\070', '\066', '\040', '\063', '\056', '\060', '\000', '\005', 
  89. '\002', '\235', '\001', '\150', '\000', '\200', '\002', '\200', 
  90. '\000', '\144', '\000', '\062', '\000', '\000', '\004', '\000', 
  91. '\000', '\000', '\004', '\000', '\000', '\002', '\020', '\002', 
  92. '\000', '\037', '\000', '\000', '\000', '\000', '\000', '\000', 
  93. '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 
  94. '\000', '\000', '\000', '\000', '\000', '\057', '\143', '\040', 
  95. '\146', '\157', '\157', '\056', '\142', '\141', '\164', '\000', 
  96. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  97. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  98. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  99. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  100. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  101. '\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040', 
  102. '\040', '\040', '\040', '\040', '\040', '\127', '\111', '\116', 
  103. '\104', '\117', '\127', '\123', '\040', '\062', '\070', '\066', 
  104. '\040', '\063', '\056', '\060', '\000', '\377', '\377', '\033', 
  105. '\002', '\006', '\000', '\000', '\000', '\000', '\000', '\000', 
  106. '\000'
  107. };
  108.  
  109. static HINSTANCE hInstance;
  110.  
  111.  
  112. /*
  113.  *----------------------------------------------------------------------
  114.  *
  115.  * LibMain --
  116.  *
  117.  *      16-bit DLL entry point.
  118.  *
  119.  * Results:
  120.  *      Returns 1.
  121.  *
  122.  * Side effects:
  123.  *      None.
  124.  *
  125.  *----------------------------------------------------------------------
  126.  */
  127.  
  128. int CALLBACK
  129. LibMain(
  130.     HINSTANCE hinst,
  131.     WORD wDS,
  132.     WORD cbHeap,
  133.     LPSTR unused)
  134. {
  135.     hInstance   = hinst;
  136.     wDS         = wDS;          /* lint. */
  137.     cbHeap      = cbHeap;       /* lint. */
  138.     unused      = unused;       /* lint. */
  139.  
  140.     return TRUE;
  141. }
  142.  
  143. /*
  144.  *----------------------------------------------------------------------
  145.  *
  146.  * UTProc --
  147.  *
  148.  *      Universal Thunk dispatch routine.  Executes a 16-bit DOS
  149.  *      application or a 16-bit or 32-bit Windows application and
  150.  *      waits for it to complete.
  151.  *
  152.  * Results:
  153.  *      1 if the application could be run, 0 or -1 on failure.
  154.  *
  155.  * Side effects:
  156.  *      Executes 16-bit code.
  157.  *
  158.  *----------------------------------------------------------------------
  159.  */
  160.  
  161. int WINAPI
  162. UTProc(buf, func)
  163.     void *buf;
  164.     DWORD func;
  165. {
  166.     char **args;
  167.  
  168.     args = (char **) buf;
  169.     if (func == 0) {
  170.     return DosSpawn(args[0], args[1], args[2]);
  171.     } else {
  172.     return WinSpawn(args[0]);
  173.     }
  174. }
  175.  
  176. /*
  177.  *-------------------------------------------------------------------------
  178.  *
  179.  * WinSpawn --
  180.  *
  181.  *      Start a 16-bit or 32-bit Windows application with optional 
  182.  *      command line arguments and wait for it to finish.  Windows 
  183.  *      applications do not handle input/output redirection.
  184.  *
  185.  * Results:
  186.  *      The return value is 1 if the application could be run, 0 otherwise.
  187.  *
  188.  * Side effects:
  189.  *      Whatever the application does.
  190.  *
  191.  *-------------------------------------------------------------------------
  192.  */
  193.  
  194. static int
  195. WinSpawn(command)
  196.     char *command;              /* The command line, consisting of the name
  197.                  * of the executable to run followed by any
  198.                  * number of arguments to the executable. */
  199. {
  200.     return WaitForExit(WinExec(command, SW_SHOW));
  201. }
  202.  
  203. /*
  204.  *---------------------------------------------------------------------------
  205.  *
  206.  * DosSpawn --
  207.  *
  208.  *      Start a 16-bit DOS program with optional command line arguments
  209.  *      and wait for it to finish.  Input and output can be redirected
  210.  *      from the specified files, but there is no such thing as stderr 
  211.  *      under Win32s.
  212.  *      
  213.  *      This procedure to constructs a temporary .pif file that wraps a
  214.  *      temporary .bat file that runs the 16-bit application.  The .bat
  215.  *      file is necessary to get the redirection symbols '<' and '>' to 
  216.  *      work, because WinExec() doesn't accept them.  The .pif file is
  217.  *      necessary to cause the .bat file to run in an iconified window,
  218.  *      to avoid having a large DOS box pop up, obscuring everything, and 
  219.  *      then almost immediately flicker out of existence, which is rather 
  220.  *      disconcerting.
  221.  *
  222.  * Results:
  223.  *      The return value is 1 if the application could be run, 0 otherwise.
  224.  *
  225.  * Side effects:
  226.  *      Whatever the application does.
  227.  *
  228.  *---------------------------------------------------------------------------
  229.  */
  230.  
  231. static int
  232. DosSpawn(command, fromFileName, toFileName)
  233.     char *command;              /* The name of the program, plus any
  234.                  * arguments, to be run. */
  235.     char *fromFileName;         /* Standard input for the program is to be
  236.                  * redirected from this file, or NULL for no
  237.                  * standard input. */
  238.     char *toFileName;           /* Standard output for the program is to be
  239.                  * redirected to this file, or NULL to
  240.                  * discard standard output. */
  241. {
  242.     int result;
  243.     HFILE batFile, pifFile;
  244.     char batFileName[144], pifFileName[144];
  245.  
  246.     GetTempFileName(0, "tcl", 0, batFileName);
  247.     unlink(batFileName);
  248.     strcpy(strrchr(batFileName, '.'), ".bat");
  249.     batFile = _lcreat(batFileName, 0);
  250.  
  251.     GetTempFileName(0, "tcl", 0, pifFileName);
  252.     unlink(pifFileName);
  253.     strcpy(strrchr(pifFileName, '.'), ".pif");
  254.     pifFile = _lcreat(pifFileName, 0);
  255.  
  256.     _lwrite(batFile, command, strlen(command));
  257.     if (fromFileName == NULL) {
  258.     _lwrite(batFile, " < nul", 6);
  259.     } else {
  260.     _lwrite(batFile, " < ", 3);
  261.     _lwrite(batFile, fromFileName, strlen(fromFileName));
  262.     }
  263.     if (toFileName == NULL) {
  264.     _lwrite(batFile, " > nul", 6);
  265.     } else {
  266.     _lwrite(batFile, " > ", 3);
  267.     _lwrite(batFile, toFileName, strlen(toFileName));
  268.     }
  269.     _lwrite(batFile, "\r\n\032", 3);
  270.     _lclose(batFile);
  271.  
  272.     strcpy(pifData + 0x1c8, batFileName);
  273.     _lwrite(pifFile, pifData, sizeof(pifData));
  274.     _lclose(pifFile);
  275.  
  276.     result = WaitForExit(WinExec(pifFileName, SW_MINIMIZE));
  277.  
  278.     unlink(pifFileName);
  279.     unlink(batFileName);
  280.  
  281.     return result;
  282. }
  283.  
  284. /*
  285.  *-------------------------------------------------------------------------
  286.  *
  287.  * WaitForExit --
  288.  *
  289.  *      Wait until the application with the given instance handle has
  290.  *      finished.  PeekMessage() is used to yield the processor; 
  291.  *      otherwise, nothing else could execute on the system.
  292.  *
  293.  * Results:
  294.  *      The return value is 1 if the process exited successfully,
  295.  *      or 0 otherwise.
  296.  *
  297.  * Side effects:
  298.  *      None.
  299.  *
  300.  *---------------------------------------------------------------------------
  301.  */
  302.  
  303. static int
  304. WaitForExit(inst)
  305.     int inst;                   /* Identifies the instance handle of the
  306.                  * process to wait for. */
  307. {
  308.     TASKENTRY te;
  309.     MSG msg;
  310.     UINT timer;
  311.  
  312.     if (inst < 32) {
  313.     return 0;
  314.     }
  315.  
  316.     te.dwSize = sizeof(te);
  317.     te.hInst = 0;
  318.     TaskFirst(&te);
  319.     do {
  320.     if (te.hInst == (HINSTANCE) inst) {
  321.         break;
  322.     }
  323.     } while (TaskNext(&te) != FALSE);
  324.  
  325.     if (te.hInst != (HINSTANCE) inst) {
  326.     return 0;
  327.     }
  328.  
  329.     timer = SetTimer(NULL, 0, 0, NULL);
  330.     while (1) {
  331.     if (GetMessage(&msg, NULL, 0, 0) != 0) {
  332.         TranslateMessage(&msg);
  333.         DispatchMessage(&msg);
  334.     }
  335.     TaskFirst(&te);
  336.     do {
  337.         if (te.hInst == (HINSTANCE) inst) {
  338.         break;
  339.         }
  340.     } while (TaskNext(&te) != FALSE);
  341.  
  342.     if (te.hInst != (HINSTANCE) inst) {
  343.         KillTimer(NULL, timer);
  344.         return 1;
  345.     }
  346.     }
  347. }
  348.